/***
 * Copyright (c) 2009 Yuri Feitosa Negocio - yurinegocio@gmail.com
 * All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 * 	http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License. 
 *
 */
package br.com.yx.vraptor.security.interceptor;

import java.io.IOException;

import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

import br.com.caelum.vraptor.InterceptionException;
import br.com.caelum.vraptor.Intercepts;
import br.com.caelum.vraptor.core.InterceptorStack;
import br.com.caelum.vraptor.core.MethodInfo;
import br.com.caelum.vraptor.core.RequestInfo;
import br.com.caelum.vraptor.interceptor.Interceptor;
import br.com.caelum.vraptor.ioc.RequestScoped;
import br.com.caelum.vraptor.resource.ResourceMethod;
import br.com.yx.vraptor.security.Audit;
import br.com.yx.vraptor.security.SecurityHandler;
import br.com.yx.vraptor.security.Protect;
import br.com.yx.vraptor.security.Util;


@Intercepts
@RequestScoped
/**
 * Implementação do Interceptor de Segurança
 * @author Yuri Feitosa Negócio (yurinegocio@gmail.com)
 *
 */
public class SecurityInterceptor implements Interceptor {
	public static final Logger logger = Logger.getLogger(SecurityInterceptor.class);
	private SecurityHandler loginHandler;
	private HttpServletResponse response;
	private Audit audit;
	public SecurityInterceptor(HttpServletResponse response, SecurityHandler loginHandler, Audit audit) {
		
		this.response= response;  
		this.loginHandler = loginHandler;
		this.audit = audit;
	}

	public boolean accepts(ResourceMethod method) {
		if (method.containsAnnotation(Protect.class)) {
			return true;
		} else {
			return false;
		}
	}

	public void intercept(InterceptorStack stack, ResourceMethod method,
			Object resourceInstance) throws InterceptionException {
		
		Protect p = method.getMethod().getAnnotation(Protect.class);
		
		if (p==null) { stack.next(method, resourceInstance); } // continua a execução
		
		if (logger.isDebugEnabled()) {
			logger.debug("Protecting method: " + method.getMethod().getName() + " Allowed Roles: " + Util.generateCSV(p.roles()) );
		}
		
		if ((isUserInRoles(p.roles()))||(p.annonymous())) {
			if (p.audit()) {
				this.audit.allowed(method, resourceInstance);
			}
			stack.next(method, resourceInstance); // continua a execução
			
		} else {
			if (p.audit()) {
				this.audit.denied(method, resourceInstance);
			}
			try {
				this.response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
			} catch (IOException e) {
				throw new InterceptionException(e);
			}
		}
		
	}
	
	private boolean isUserInRoles(String[] roles) {
		if (this.loginHandler.getUser()==null) return false;
		
		for (String role : roles) {
			if (this.loginHandler.getUser().isUserInRole(role)) return true;
		}
		return false;
	}

}
